package swingxrcp.framework.server.action;

import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import swingxrcp.framework.server.environment.Environment;
import swingxrcp.framework.util.log.Logger;
import swingxrcp.framework.util.log.LoggerFactory;
import swingxrcp.framework.util.serialize.JavaSerializer;
import swingxrcp.framework.util.serialize.JsonSerializer;
import swingxrcp.framework.util.serialize.Serializer;

/**
 * RCP应用Action请求代理Servlet实现.
 * <p>
 * web.xml配置：
 * <pre>
 * &lt;servlet&gt;
 *     &lt;servlet-name&gt;action&lt;/servlet-name&gt;
 *     &lt;servlet-class&gt;swingxrcp.framework.server.action.RcpActionServlet&lt;/servlet-class&gt;
 *     &lt;init-param&gt;
 *         &lt;param-name&gt;data&lt;/param-name&gt;
 *         &lt;param-value&gt;swingxrcp.framework.util.serialize.JavaSerializer&lt;/param-value&gt;
 *     &lt;/init-param&gt;
 *     &lt;init-param&gt;
 *         &lt;param-name&gt;json&lt;/param-name&gt;
 *         &lt;param-value&gt;swingxrcp.framework.util.serialize.JsonSerializer&lt;/param-value&gt;
 *     &lt;/init-param&gt;
 *     &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
 * &lt;/servlet&gt;
 * &lt;servlet-mapping&gt;
 *     &lt;servlet-name&gt;action&lt;/servlet-name&gt;
 *     &lt;url-pattern&gt;*.data&lt;/url-pattern&gt;
 * &lt;/servlet-mapping&gt;
 * &lt;servlet-mapping&gt;
 *     &lt;servlet-name&gt;action&lt;/servlet-name&gt;
 *     &lt;url-pattern&gt;*.json&lt;/url-pattern&gt;
 * &lt;/servlet-mapping&gt;
 * </pre>
 *
 * @author liangfei
 *
 */
public class ActionServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	/**
	 * 日志输出接口
	 */
	protected final Logger logger = LoggerFactory.getLogger(getClass());

	protected ActionProcesser actionProcesser;

	protected Map<String, Serializer> serializers;

	@SuppressWarnings("unchecked")
	@Override
	public void init() throws ServletException {
		super.init();
		ActionFactory actionFactory = Environment.initEnvironment(getServletContext());
		this.actionProcesser = new ActionProcesser(actionFactory, null); // TODO 从配置中读取拦截器
		this.serializers = new HashMap<String, Serializer>();
		Enumeration<String> enumeration = super.getInitParameterNames();
		while (enumeration.hasMoreElements()) {
			String name = enumeration.nextElement();
			if (name == null)
				continue;
			name = name.trim();
			String className = super.getInitParameter(name);
			if (className == null)
				continue;
			className = className.trim();
			try {
				Class<?> cls = Class.forName(className);
				Serializer serializer = (Serializer)cls.newInstance();
				serializers.put(name, serializer);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		// 注入缺省序列化器
		if (serializers.size() == 0) {
			serializers.put("data", new JavaSerializer());
			serializers.put("json", new JsonSerializer());
		}
	}

	@Override
	public void destroy() {
		super.destroy();
		Environment.destroyEnvironment();
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String actionName = request.getRequestURI();
		String context = request.getContextPath();
		if (context != null && ! "/".equals(context))
			actionName = actionName.substring(context.length());
		if (actionName.startsWith("/"))
			actionName = actionName.substring(1);
		int suffixIndex = actionName.lastIndexOf('.');
		if (suffixIndex < 0 || suffixIndex >= actionName.length())
			throw new ServletException("Action suffix is required!");
		String suffix = actionName.substring(suffixIndex + 1);
		actionName = actionName.substring(0, suffixIndex);
		Serializer serializer = serializers.get(suffix);
		if (serializer == null)
			throw new NullPointerException("Not found serializer by suffix: " + suffix);
		Serializable object = serializer.deserialize(request.getInputStream()); // 反序列化读取客户端传过来的对象
		Serializable result = actionProcesser.process(actionName, object);
		serializer.serialize(result, response.getOutputStream()); // 序列化结果到客户端
	}

}
